/**
 * 
 */
package jvs.peer.test;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.net.URI;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.Properties;
import java.util.StringTokenizer;

import jvs.peer.io.ChannelManager;
import jvs.peer.net.PeerSocket;

/**
 * @author qiangli
 * 
 */
public class PeerClient {
	private static final int BUFSIZE = 1024;

	public PeerClient() {
	}

	protected String encodeFormData(String[][] data)
			throws UnsupportedEncodingException {
		StringBuilder sb = new StringBuilder();

		for (int i = 0; i < data.length; i++) {
			if (i > 0) {
				sb.append("&");
			}
			sb.append(URLEncoder.encode(data[i][0], "UTF-8"));
			sb.append("=");
			sb.append(URLEncoder.encode(data[i][1], "UTF-8"));
		}
		return sb.toString();
	}

	public void post(String peer, String uri, String[][] params, OutputStream os)
			throws IOException {
		try {
			String data = encodeFormData(params);
			Socket c = new PeerSocket(peer);
			OutputStream out = c.getOutputStream();
			PrintWriter w = new PrintWriter(out);
			w.print("POST " + uri + " HTTP/1.1\r\n");
			w.print("Host: localhost\r\n");
			w.print("Content-Type: application/x-www-form-urlencoded\r\n");
			w.print("Content-Length: " + data.length() + "\r\n");
			w.print("\r\n");
			w.append(data);
			w.flush();
			w.close();
			//
			InputStream is = c.getInputStream();
			copy(is, os);

		} catch (IOException e) {
			throw e;
		}

	}

	public int get(final String peer, final String uri, OutputStream os)
			throws Exception {
		final Socket c = new PeerSocket(peer);
		final OutputStream out = c.getOutputStream();
//		final PrintWriter w = new PrintWriter(out);
//
//		w.print("GET " + uri + " HTTP/1.1\r\n");
//		w.print("Host: 1.0.0.127\r\n");
//		w.print("Connection: close\r\n");
//		w.print("\r\n");
//		w.flush();

		out.write(("GET " + uri + " HTTP/1.1\r\n").getBytes());
		out.write("Host: 1.0.0.127\r\nConnection: close\r\n\r\n".getBytes());
		out.flush();
		//
		InputStream in = c.getInputStream();
		StringBuilder header = new StringBuilder();
		byte[] buf = new byte[BUFSIZE];
		int cnt = 0;
		int state = 0;
		boolean done = false;
		while (!done) {
			int ch = in.read();
			switch (state) {
			case 0:
				if (ch == '\r') {
					state++;
				}
				break;
			case 1:
				if (ch == '\n') {
					state++;
				} else {
					state = 0;
				}
				break;
			case 2:
				if (ch == '\r') {
					state++;
				} else {
					state = 0;
				}
				break;
			case 3:
				if (ch == '\n') {
					done = true;
					break;
				} else {
					state = 0;
				}
			default:
			}
			buf[cnt++] = (byte) ch;
			if (cnt == buf.length) {
				header.append(new String(buf, 0, cnt));
				cnt = 0;
			}
		}
		if (cnt > 0 && header != null) {
			header.append(new String(buf, 0, cnt));
		}

		StringTokenizer st = new StringTokenizer(header.toString());
		st.nextToken(); // skip HTTP/1.x
		String status = st.nextToken();

		if (status.charAt(0) != '2') {
			while ((in.read(buf)) != -1) {
				;
			}
			return -1;
		}
		//
		// InputStream cin = new ChunkedInputStream(in);
		copy(in, os);
		//
		in.close();
		out.close();
		return cnt;
	}

	private int copy(InputStream in, OutputStream out) throws IOException {
		byte[] buf = new byte[BUFSIZE];
		int cnt = 0;
		String thn = Thread.currentThread().toString();
		while (true) {
			int read = in.read(buf);
			if (read > 0) {
				cnt += read;
				out.write(buf, 0, read);
				out.flush();

				System.err.println(thn + " count: " + cnt);
			} else {
				break;
			}
		}
		return cnt;
	}

	public static void main(String[] args) {
		try {
			Properties attrs = System.getProperties();
			attrs.load(new FileInputStream(
					"C:/workspace/jvs2/resource/user1.txt"));

			ChannelManager cm = ChannelManager.getInstance();
			cm.init(attrs);
			cm.startup();

			final String peerid = attrs.getProperty("xmpp.peer");
			final String[] addr = cm.getNetAddress(peerid);

			System.out.println("addr: "
					+ (addr == null ? null : Arrays.asList(addr)));

			final PeerClient cl = new PeerClient();

			// ByteArrayOutputStream bos = new ByteArrayOutputStream();
			// cl.post("client@niwota.info","/bin", new String[][] {
			// {"filepath","/path"},
			// {"options","none"}
			// },bos);

			File file = new File("C:/temp/out_images.png");
			OutputStream os = new FileOutputStream(file);
			// final OutputStream os = System.err;
			String image = URLEncoder
					.encode("content://media/external/images/media/3297"); // 3296
																			// 3297
																			// 3295
																			// 3222
			final URI[] uris = {
			// new URI("/web/help.html") ,
			// new URI("/content/info.niwota.frames/jsonp/frame/listFrames"),
			// new
			// URI("/content/info.niwota.frames/jsonp/frame/loadFrame?label=Pictures"),
			// new URI("/content/info.niwota.frames/bin/image?uri="+image),
			// new URI("/content/info.niwota.frames/bin/thumbnail?uri="+image),
			new URI("/content/info.niwota.frames/bin/vignette?uri=" + image) };

			for (int i = 0; i < uris.length; i++) {
				final String uri = uris[i].toString();
				// Thread t = new Thread() {
				// public void run() {
				//
				// }
				// };
				// t.start();

				try {
					System.err.println("************ uri: " + uri);
					cl.get(peerid, uri, os);
					os.flush();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}

			os.close();
			System.err.println("done!");
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.exit(0);
	}
}
